using System;
using OhioState.Graphics;
using Tao.OpenGl;


namespace OhioState.Graphics.OpenGL
{
    public class RenderableTexture2DGL2 : IRenderTarget, IOpenGLResource
    {
        public RenderableTexture2DGL2(ITexture _tex2DHandler )
        {
            _tex2DTarget = _tex2DHandler;
        }

        public void enableFrameBuffer()
        {
            createFrameBuffer();
            //enable the framebuffer object
            Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, _fbID);

            Gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);

        }

        public void disableFrameBuffer()
        {
            Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0);
        }

        internal void bindTexToFrameBuffer()
        {
            Gl.glActiveTexture(Gl.GL_TEXTURE0);
            _tex2DTarget.bind();
            //enable the framebuffer object
            Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, _fbID);

            uint textureGUID = (_tex2DTarget as IOpenGLResource).GUID; 
            Gl.glFramebufferTexture2DEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT,
                                          Gl.GL_TEXTURE_2D, textureGUID, 0);

        }

        #region IOpenGLResource Members
        public uint GUID
        {
            get { return _fbID; }
        }
        #endregion

        private void createFrameBuffer()
        {
            if (!_created)
            {
                _created = true;
                Gl.glGenFramebuffersEXT(1, out _fbID);
                //bind texture to framebuffer
                bindTexToFrameBuffer();
                if (!checkFramebufferStatus())
                    throw new ApplicationException("Error in creating the FBO");
            }
        }

        private void deleteFrameBuffer()
        {
            Gl.glDeleteFramebuffersEXT(1, ref _fbID);
            // delete the textures
            //int texid = 0;

            //texid = _tex2DTarget.TextureID;
            //Gl.glDeleteTextures(1, ref texid);

        }

        private bool checkFramebufferStatus()
        {
            String info = String.Empty;
            int status;
            status = (int)Gl.glCheckFramebufferStatusEXT(Gl.GL_FRAMEBUFFER_EXT);
            switch (status)
            {
                case Gl.GL_FRAMEBUFFER_COMPLETE_EXT:
                    return true;
                case Gl.GL_FRAMEBUFFER_UNSUPPORTED_EXT:
                    info = "Unsupported framebuffer format\n";
                    break;
                case Gl.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
                    info = "Framebuffer incomplete, missing attachment\n";
                    break;
                //case Gl.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
                //    info = "Framebuffer incomplete, duplicate attachment\n";
                //    break;
                case Gl.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
                    info = "Framebuffer incomplete, attached images must have same dimensions\n";
                    break;
                case Gl.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
                    info = "Framebuffer incomplete, attached images must have same format\n";
                    break;
                case Gl.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
                    info = "Framebuffer incomplete, missing draw buffer\n";
                    break;
                case Gl.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
                    info = "Framebuffer incomplete, missing read buffer\n";
                    break;
                default:
                    info = "Frame Buffer Object error";
                    break;
            }
            return false;
        }

        private bool _created = false;
        private uint _fbID;
        private ITexture _tex2DTarget;
    }

}
